package com.enerccio.commonJ.objects;

import com.enerccio.commonJ.objects.Condition.ConditionException;
import com.enerccio.commonJ.system.VM;
import com.enerccio.commonJ.utils.Setfable;

/**
 * Represents symbols in commonJ, along with their values and plists stored.
 * @author enerccio
 *
 */
public final class Symbol extends commonJObject {
	
	/**
	 * Creates new symbol for the package.
	 * @param name
	 * @param pack
	 * @return
	 * @throws ConditionException 
	 */
	public static synchronized Symbol newSymbol(String name, commonJPackage pack){
		Symbol interned;
		try {
			interned = pack.get(name);
		} catch (Exception e) {
			interned = new Symbol(pack, name);
		}
		return interned;
	}
	
	/**
	 * Creates symbol from name and current *package* of current VM
	 * @param qualifiedName
	 * @return
	 * @throws ConditionException 
	 */
	public static synchronized Symbol newSymbol(String qualifiedName) throws ConditionException{
		try {
			// TODO
		} catch (Exception e){
			new Condition(e.getMessage());
		}
		return null;
	}
	
	/**
	 * Creates new keyword symbol from tasteful name.
	 * @param keywordName
	 * @return
	 */
	public static synchronized Symbol newKeyword(String keywordName) {
		return newSymbol(keywordName, VM.getVM().getKeywordsPackage());
	}
	
	/**
	 * Creates new gensym with gensymName name
	 * @param gensymName
	 * @return
	 */
	public static synchronized Symbol newGensym(String gensymName){
		return newSymbol(gensymName, null); // no package can own it
	}
	
	private String name;
	private commonJPackage owner;
	private ConsCell plist;
	
	private boolean special;
	
	private Symbol(){
		this.plist = ConsCell.NIL;
		this.special = false;
	}
	
	private Symbol(commonJPackage owner, String name){
		this();
		this.name = name;
		this.owner = owner;
		if (owner != null)
			owner.addSymbol(name, this);
	}
	
	public String getName(){
		return name;
	}
	
	public commonJPackage getOwningPackage(){
		return owner;
	}
	
	@Setfable
	public synchronized ConsCell getPList(){
		return plist;
	}
	
	public synchronized void setfGetPList(ConsCell argument){
		plist = argument;
	}
	
	public synchronized boolean isSpecial(){
		return special;
	}
	
	public synchronized void setSpecial(boolean spec){
		special = spec;
	}
	
	@Override
	public synchronized String toString(){
		if (owner == null)
			return "|GENSYM: " + name + "|"; // gensymmed
		
		VM vm = VM.getVM();
		if (owner == vm.getKeywordsPackage()){
			// it is a keyword, return :+name
			return ":"+name;
		}
		return name;
	}

}
